#include "mux_demo.h"

#define DEAD_LOCK 0
#define BUF_SIZE 10

char p_write_pos=0, p_read_pos=0, c_read_pos=0;
UINT8 buf_src[BUF_SIZE], buf_dst[BUF_SIZE];
UINT32 tid_c, tid_p1, tid_p2;
UINT32 sem, mux_read, mux_write;

static void customer_entry(VOID) {
    UINT32 ret;
	uint8_t i;
	while(1)
	{
		printf("customer try get sem...\n");
		// 申请信号量，无限等待
		ret = LOS_SemPend(sem, LOS_WAIT_FOREVER);
		if (ret != LOS_OK) { printf("customer get sem error\n"); return ; }
		printf("customer get sem success\n");
		printf("dst data is : %d\n", buf_dst[c_read_pos++]);
		if(c_read_pos >= BUF_SIZE)
			break;
	}
    return;
}
#if DEAD_LOCK
// 生产者任务，给buf赋值
static void producer1_entry(VOID) {
	UINT32 ret;

    while (1) {
		// 加锁,获取操作read_pos的权利
		LOS_MuxPend(mux_write, LOS_WAIT_FOREVER);
		printf("producer1 is reading pos ... %d\n", p_read_pos);
		LOS_MDelay(200);
		if(p_read_pos<BUF_SIZE){
			// 加锁,获取操作write_pos的权利
			LOS_MuxPend(mux_read, LOS_WAIT_FOREVER);
			printf("producer1 is copy data ...\n");
			buf_dst[p_write_pos] = buf_src[p_read_pos];
			p_write_pos++;
			LOS_SemPost(sem);
			// 释放锁
			LOS_MuxPost(mux_read);
			p_read_pos++;
			// 释放锁
			LOS_MuxPost(mux_write);
		}
		else{
			printf("producer1 is over ...\n");
			// 释放锁
			LOS_MuxPost(mux_write);
			return;
		}
        LOS_MDelay(200);
    }
    return;
}
#else
// 生产者任务，给buf赋值
static void producer1_entry(VOID) {
	UINT32 ret;

    while (1) {
		// 加锁,获取操作read_pos的权利
		LOS_MuxPend(mux_read, LOS_WAIT_FOREVER);
		printf("producer1 is reading pos ... %d\n", p_read_pos);
		if(p_read_pos<BUF_SIZE){
			// 加锁,获取操作write_pos的权利
			LOS_MuxPend(mux_write, LOS_WAIT_FOREVER);
			printf("producer1 is copy data ...\n");
			buf_dst[p_write_pos] = buf_src[p_read_pos];
			p_write_pos++;
			// 释放信号
			LOS_SemPost(sem);
			// 释放锁
			LOS_MuxPost(mux_write);
			p_read_pos++;
			// 释放锁
			LOS_MuxPost(mux_read);
		}
		else{
			printf("producer1 is over ...\n");
			// 释放锁
			LOS_MuxPost(mux_read);
			return;
		}
        LOS_MDelay(200);
    }
    return;
}
#endif
static void producer2_entry(VOID) {
	UINT32 ret;

    while (1) {
		// 加锁,获取操作read_pos的权利
		LOS_MuxPend(mux_read, LOS_WAIT_FOREVER);
		printf("producer2 is reading pos ... %d\n", p_read_pos);
		if(p_read_pos<BUF_SIZE){
			// 加锁,获取操作write_pos的权利
			LOS_MuxPend(mux_write, LOS_WAIT_FOREVER);
			printf("producer2 is copy data...\n");
			buf_dst[p_write_pos] = buf_src[p_read_pos];
			p_write_pos++;
			LOS_SemPost(sem);
			// 释放锁
			LOS_MuxPost(mux_write);
			p_read_pos++;
			// 释放锁
			LOS_MuxPost(mux_read);
		}
		else{
			// 释放锁
			LOS_MuxPost(mux_read);
			printf("producer2 is over...\n");
			return;
		}
        LOS_MDelay(1000);
    }
    return;
}

static UINT32 my_task(UINT32 tid, char *name, UINT16 pri, UINT32 stack_size, TSK_ENTRY_FUNC func) {
    UINT32 ret;
    TSK_INIT_PARAM_S param={0};

    // 锁住任务调度，防止高优先级任务调度
    LOS_TaskLock();
    // 任务名字
    param.pcName = name;
    // 任务入口地址
    param.pfnTaskEntry = func;
    // 任务优先级
    param.usTaskPrio = pri;
    // 任务栈
    param.uwStackSize = stack_size;
    // 调用系统函数，创建任务。成功之后任务处于就绪状态
    ret = LOS_TaskCreate(&tid, &param);
	// 创建任务失败
    if (ret != LOS_OK) { printf("create task failed, errno = %x\n", ret); }
    //解锁任务调度
    LOS_TaskUnlock();

    return ret;
}

UINT32 mux_entry(){
	UINT32 ret;

	// 缓冲区赋初值
	uint8_t i;
	for(i=0; i<BUF_SIZE; i++)
		buf_src[i] = i*2;

	// 创建信号量，初始状态没有资源
   	ret = LOS_SemCreate(0, &sem);
    if(ret != LOS_OK){ printf("create create sem failed\n"); return 0; }
	// 创建互斥锁
   	ret = LOS_MuxCreate(&mux_read);
    if(ret != LOS_OK){ printf("create create mux_read failed\n"); return -1; }
	ret = LOS_MuxCreate(&mux_write);
    if(ret != LOS_OK){ printf("create create mux_write failed\n"); return -1; }

	// 创建消费者任务
	ret = my_task(&tid_c, "customer", 9, 0x2000, customer_entry);
	if(ret != LOS_OK){ printf("create producer1 failed\n"); return -1; }
	// 创建生产者任务
	ret = my_task(&tid_p1, "producer1", 10, 0x2000, producer1_entry);
	if(ret != LOS_OK){ printf("create producer1 failed\n"); return -1; }
	ret = my_task(&tid_p2, "producer1", 10, 0x2000, producer2_entry);
	if(ret != LOS_OK){ printf("create producer2 failed\n"); return -1; }

	return ret;
}

// SYS_RUN(mux_entry);